'use strict';

const jwt = require('koa-jwt');
const { match } = require('path-to-regexp');

module.exports = options => {
  return async function(ctx, next) {
    const ignoreJwt = checkIgnore(ctx, options);
    if (ignoreJwt) return next();
    await jwt(options)(ctx, async () => {
      const { usr } = ctx.state.payload;
      const user = await ctx.model.User.findById(usr).lean();
      if (!user) throw ctx.error(404, '用户不存在');
      ctx.state.user = user;
      await next();
    });
  };
};

function checkIgnore(ctx, options) {
  if (!Array.isArray(options.unless)) return false;
  return options.unless.some(it => {
    let path,
      method;
    if (typeof it === 'string' || it instanceof RegExp) {
      path = it;
    } else if (typeof it === 'object' && it != null) {
      path = it.path;
      method = it.method;
    }
    const matchPath = path === undefined || match(path, { decode: decodeURIComponent })(ctx.path);
    const methods = method && method.trim().split(',').filter(m => m)
      .map(m => m.trim().toUpperCase());
    const matchMethod = method === undefined || methods.includes(ctx.method);
    return matchPath && matchMethod;
  });
}
